class Driver(object):
    def __init__(self):
        super(Driver, self).__init__()
        self.__signal = {}
        
    def check(self, kind):
        """ check this kind signal, true means have some """
        if self.__signal.has_key(kind) and len(self.__signal[kind]) > 0: return True
        else: return False
    
    def pop(self, kind):
        """ return this kind top one, and delete it """
        if self.__signal.has_key(kind):
            sig = self.__signal[kind][0]
            del self.__signal[kind][0]
            return sig
        else: 
            return None
        
    def receive(self, kind):
        """ return all this kind signal """
        if self.__signal.has_key(kind): return self.__signal[kind]
        else: return []
    
    def send(self, sig, overwrite = False):
        """ send a signal to driver """
        if not self.__signal.has_key(sig.KIND):
            self.__signal[sig.KIND] = []
        if overwrite: self.clear(sig.KIND) # simply clear to process overwrite
        self.__signal[sig.KIND].append(sig)
        
    def clear(self, kind = None):
        """ clear all signal of this kind, or any kind """
        if not kind: self.__signal = {}
        elif self.__signal.has_key(kind): self.__signal[kind] = [] # why not 'del'? for resuable
      
################################################
# signal classes
################################################
class Signal(object):
    def __init__(self, kind):
        super(Signal, self).__init__()
        self.kind = kind
        
class KeySignal(Signal):
    KIND = 'key'
    def __init__(self, keyname):
        super(KeySignal, self).__init__(KeySignal.KIND)
        self.key = keyname # from pygame.locals

class PathSignal(Signal):
    KIND = 'path'
    UP = 0
    LEFT = 1
    DOWN = 2
    RIGHT = 3
    def __init__(self, direct, force = True):
        super(PathSignal, self).__init__(PathSignal.KIND)
        self.direct = direct
        self.force = force # if collided, discard this path point or wait while can reach this path point

class GotoSignal(Signal): # why split GotoSignal & PathSignal? for animate
    KIND = 'goto'
    UP = (0, -1)
    DOWN = (0, 1)
    LEFT = (-1, 0)
    RIGHT = (1, 0)
    DIR2VEC = [(0, -1), (-1, 0), (0, 1), (1, 0)]
    def __init__(self, dirvec):
        super(GotoSignal, self).__init__(GotoSignal.KIND)
        self.dirvec = dirvec
        self.distance = 16 # one step one grid 

class CollisionSignal(Signal):
    KIND = 'collision'
    def __init__(self, spr = None):
        super(CollisionSignal, self).__init__(CollisionSignal.KIND)
        self.spr = spr # if spr is None, means collide map bound

class ProduceSignal(Signal):
    KIND = 'produce'
    def __init__(self, rate, sprcls, *args, **keywords):
        super(ProduceSignal, self).__init__(ProduceSignal.KIND)
        self.rate = rate # produce rate of this sprite
        self.sprcls = sprcls # class refrence
        self.args = args
        self.keywords = keywords

class ChildrenSignal(Signal):
    KIND = 'children'
    def __init__(self, *args):
        super(ChildrenSignal, self).__init__(ChildrenSignal.KIND)
        self.args = args









